home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / compress / tar321__.zip / SOURCES.ZIP / DISK.C < prev    next >
C/C++ Source or Header  |  1997-03-09  |  10KB  |  332 lines

  1. /* disk.c - MS-DOS diskette service for Tar program (see file tar.c)
  2.  * Author: T.V.Shaporev
  3.  * Prepared for release 19 Oct 1990
  4.  *
  5.  * Called by readtape(), writetape() etc. - see file tape.c
  6.  */
  7. #include "sysup.h"
  8. #ifdef __TURBOC__
  9.  
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <dos.h>
  13.  
  14. #include "modern.h"
  15. #include "define.h"
  16.  
  17. #define QUADISK '\200'
  18. #define RAINBOW '\201'
  19. #define SMT     '\x18' /* Set Media Type */
  20.  
  21. extern int  diskserv __ARGS__((int, int, int, int, int, int, void far *));
  22. extern void far *diskspec __ARGS__((int, int, int, int, int,
  23.                                     struct BYTEREGS far *));
  24. extern void printbs  __ARGS__(( int ));
  25.  
  26. static void errdisk  __ARGS__(( int ));
  27. static void redrive  __ARGS__(( void ));
  28. static int  trydisk  __ARGS__(( int, char *, int ));
  29. static void nextdisk __ARGS__(( void ));
  30. static void skipsect __ARGS__(( void ));
  31. static void ibmdisk  __ARGS__(( int, char *, int ));
  32. static void rainbow  __ARGS__(( int, char *, int ));
  33.  
  34. #define FDC_STATUS  (*(char far *)0x0490L)
  35.  
  36. static unsigned short heads, tracks, sectors, last_seg, this_seg;
  37. static char calibr = 0;
  38.  
  39. struct   { char type_disk[16]; unsigned size, heads, tracks, sectors; }
  40.        ftab[] = { {"fd048ss8",       160,  1,     40,       8  },
  41.                   {"fd048ss9",       180,  1,     40,       9  },
  42.                   {"fd048ds8",       320,  2,     40,       8  },
  43.                   {"fd048ds9",       360,  2,     40,       9  },
  44.                   {"fd135ds9",       720,  2,     80,       9  },
  45.                   {"fd096ds9",       720,  2,     80,       9  },
  46.                   {"fd096ds15",     1200,  2,     80,      15  },
  47.                   {"fd135ds18",     1440,  2,     80,      18  },
  48.                   {"",              2880,  2,     80,      36  } };
  49.  
  50. static void errdisk(n)
  51. int n;
  52. {
  53.    register int i;
  54.    static struct { unsigned char code; char *text; } errtab[] = {
  55.    {    0, "undefined error" },
  56.    { 0x00, "no error on last operation" },
  57.    { 0x01, "invalid request to controller" },
  58.    { 0x02, "bad address mark" },
  59.    { 0x03, "write protect" },
  60.    { 0x04, "sector ID bad or not found" },
  61.    { 0x05, "reset failed" },
  62.    { 0x06, "floppy changed line on" },
  63.    { 0x08, "DMA failure" },
  64.    { 0x09, "DMA overrun: attempted to write across 64K" },
  65.    { 0x0b, "bad track flag encountered" },
  66.    { 0x0C, "media type not found" },
  67.    { 0x10, "bad CRC: invalid CRC when data checked" },
  68.    { 0x11, "recoverable error found; data corrected" },
  69.    { 0x20, "controller failure" },
  70.    { 0x40, "bad seek; requested track not found" },
  71.    { 0x80, "time out; drive did not respond" },
  72.    { 0xff, "sense operation failed" } };
  73.  
  74.    for (i=1; errtab[i].code!=n && i<dimof(errtab); i++) ;
  75.    if (i>=dimof(errtab)) i = 0;
  76.    fprintf(myout, "Tar: diskette error: %s\n", errtab[i].text);
  77. }
  78.  
  79. int argdisk(k)
  80. register k;
  81. {
  82.    register i;
  83.  
  84.    for (i=0; ftab[i].size!=k && i<dimof(ftab); i++) ;
  85.    if (i >= dimof(ftab)) return -1;
  86.    sectors  = ftab[i].sectors;
  87.    tracks   = ftab[i].tracks;
  88.    heads    = ftab[i].heads;
  89.    return 0;
  90. }
  91.  
  92. int defdev(k)
  93. register char *k;
  94. {
  95.    register i;
  96.  
  97.    for (i=0; i<dimof(ftab); i++) {
  98.       if (ftab[i].type_disk[0]!=0 && stricmp(ftab[i].type_disk, k)==0)
  99.          goto found;
  100.    }
  101.    if (stricmp("rainbow", k) == 0) {
  102.       calibr  = RAINBOW;
  103.       sectors = 10;
  104.       tracks  = 80;
  105.       heads   = 1;
  106.       return 0;
  107.    }
  108.    return -1;
  109. found:
  110.    sectors = ftab[i].sectors;
  111.    tracks  = ftab[i].tracks;
  112.    heads   = ftab[i].heads;
  113.    return 0;
  114. }
  115.  
  116. static void redrive() /* reset & recalibrate drive */
  117. {
  118.    (void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
  119.    if (calibr & QUADISK) {/* Init 800 */
  120.       FDC_STATUS = 0x61;      /* FDC status buts <- 61h - ??? */
  121.       /* verify Track 0 Sector 1 Side 0 */
  122.       (void)diskserv(4, ndrive, 0, 0, 1, 1, NULL);
  123.       /* verify Track 1 Sector 1 Side 0 */
  124.       (void)diskserv(4, ndrive, 0, 1, 1, 1, NULL);
  125.       (void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
  126.       FDC_STATUS = 0x54;      /* FDC status buts <- 54h - ??? */
  127.    } else if (calibr == SMT) {
  128.       struct BYTEREGS b;
  129.       (void)diskspec(SMT, ndrive, heads-1, tracks-1, sectors, &b);
  130.    } else if (calibr != 0) {
  131.       (void)diskserv(0x17, ndrive, 0, 0, 1, calibr, NULL);
  132.    }
  133. }
  134.  
  135. void inidisk(void)
  136. {
  137.    register j, k;
  138.    unsigned tb;
  139.    struct BYTEREGS b;
  140.    short maxhead, maxtrack, maxsect;
  141.    static unsigned short sizelist[5]  = {
  142.    /* 360K, 720K, 1.2M, 1.44M, 2.88M */
  143.       720,  1440, 2400, 2880,  5760
  144.    };
  145.    static unsigned char ctable[5][5] = {
  146.    /* Media size:  360K, 720K,   1.2M, 1.44M, 2.88M */
  147.    /* 2.88M drive */ {2, SMT,     SMT, SMT,   0},
  148.    /* 1.44M drive */ {2, SMT,     SMT, 0,     0},
  149.    /* 1.2M  drive */ {2, QUADISK, 3,   0,     0},
  150.    /* 720K  drive */ {2, 4,       0,   0,     0},
  151.    /* old   drive */ {1, 0,       0,   0,     0},
  152.    };
  153.  
  154.    if (!calibr) {
  155.       /* reset drive */
  156.       (void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
  157.       /* get drive params (set default to 2x40x9) */
  158.       (void)diskspec(8, ndrive, 1, 39, 9, &b);
  159.  
  160.       maxhead  = b.dh + 1;
  161.       maxtrack = b.ch + ((unsigned)(b.cl & 0xC0) << 2) + 1;
  162.       maxsect  = b.cl & 0x3f;
  163.  
  164.       if ((tb = maxhead * maxtrack * maxsect) == 0) {
  165.          fprintf(stderr, "Tar: drive not present\n");
  166.          done(ERINIT);
  167.       }
  168.       if (!k_flag) {
  169.          sectors = maxsect; tracks = maxtrack; heads = maxhead;
  170.          if (v_flag) fprintf(myout, "Diskette capacity %uK assigned\n", tb/2);
  171.       }
  172.       last_seg = sectors*tracks*heads;
  173.       if (last_seg == 2*2880 && tb == 2*2880) {
  174.          /* I don't know 2.88M drive geometry, so use parameters got */
  175.          sectors = maxsect; tracks = maxtrack; heads = maxhead;
  176.       }
  177.       for (j=dimof(sizelist)-1; j && sizelist[j] != tb;    j--);
  178.       for (k=dimof(sizelist)-1; k && sizelist[k]<last_seg; k--);
  179.       calibr = ctable[j][k];
  180.    }
  181.    this_seg = 0;
  182.  
  183.    redrive();
  184.  
  185.    /* get drive error status */
  186.    k = diskserv(1, ndrive, 0, 0, 1, 1, NULL);
  187.    if (k!=0 && k!=6) {
  188.       errdisk(k);
  189.       if (k!=0x11) done(ERINIT);
  190.    }
  191.    if (!cblock) {
  192.       /* Some BIOSes do strange things on quad drives.              */
  193.       /* I guess they loose info while read or write through 9th to */
  194.       /* 10th sector.  I hope, the following solves the problem.    */
  195.       printbs(cblock = a_flag ? 1 : (sectors < 9 ? sectors : 3));
  196.    }
  197. }
  198.  
  199. static int trydisk(wr, buf, bl)
  200. int wr, bl;
  201. char *buf;
  202. {
  203.    int i, k;
  204.    register short s, h, t;
  205.  
  206.    s  = this_seg % sectors + 1; /* sector */
  207.    t  = this_seg / sectors;
  208.    h  = t % heads;              /* head   */
  209.    t /= heads;                  /* track  */
  210.  
  211.    i = 0;
  212.    do {
  213.       k = diskserv((wr ? 3 : 2), ndrive, h, t, s, bl, buf);
  214. #if 0
  215.       if (!k && wr) {/* verify */
  216.          char chk[NBLOCK*BLKSIZE];
  217.          k = diskserv(4, ndrive, h, t, s, bl, buf);
  218.       }
  219. #endif
  220.       if (k) redrive();
  221.    } while (k && ++i<3);
  222.  
  223.    if (cbreak) done(0);
  224.  
  225.    if (k == 0 || k == 0x11) {
  226.       k = 0;
  227.    } else if (k!=0x02 && k!=0x04 && k!=0x0B && k!=0x10 && k!=0x40) {
  228.       errdisk(k); /* fatal error */
  229.       if (!i_flag || wr) done(wr ? EWRITE : ERREAD);
  230.    }
  231.    return k;
  232. }
  233.  
  234. static void nextdisk()
  235. {
  236.    fprintf(stderr, "Tar: insert NEXT diskette and press ENTER when ready...");
  237.    (void)yes_no('\0');
  238.    this_seg = 0;
  239.    redrive();
  240. }
  241.  
  242. static void skipsect()
  243. {
  244.    fprintf(myout, "Tar: warning: bad sector %d, skipped\n", this_seg);
  245. }
  246.  
  247. static void ibmdisk(wr, buf, bl)
  248. int wr, bl;
  249. char *buf;
  250. {
  251.    int i, j, k;
  252.  
  253.    i = sectors - this_seg % sectors;
  254.    if (i > bl) i = bl;
  255.    while (bl > 0) {
  256.       if (this_seg >= last_seg) nextdisk();
  257.       if ((k = trydisk(wr, buf, i)) == 0) {
  258.          this_seg += i;
  259.          buf      += i*BLKSIZE;
  260.          bl       -= i;
  261.       } else {
  262.          for (j=0; j<i; j++)  {
  263.             if (i>1) k = trydisk(wr, buf, 1);
  264.             if (k == 0) { /* one sector o'k */
  265.                buf += BLKSIZE;
  266.                --bl;
  267.             } else skipsect();
  268.             ++this_seg;
  269.          }
  270.       }
  271.       i = sectors < bl ? sectors : bl;
  272.    }
  273. }
  274.  
  275. static void rainbow(wr, buf, bl)
  276. int wr, bl;
  277. char *buf;
  278. {
  279.    int i, j, k, n;
  280.    static char e85tab[50] = {
  281.    /*  x  =   0   1   2   3   4   5   6   7   8   9  */
  282.    /* 0x */   1,  3,  5,  7,  9,  2,  4,  6,  8, 10,
  283.    /* 1x */   3,  5,  7,  9,  1,  4,  6,  8, 10,  2,
  284.    /* 2x */   5,  7,  9,  1,  3,  6,  8, 10,  2,  4,
  285.    /* 3x */   7,  9,  1,  3,  5,  8, 10,  2,  4,  6,
  286.    /* 4x */   9,  1,  3,  5,  7, 10,  2,  4,  6,  8,
  287.    };
  288.  
  289.    while (bl > 0) {
  290.       if (this_seg >= last_seg) nextdisk();
  291.  
  292.       i = (this_seg/10 + 1) % 80; /* track  */
  293.       j = e85tab[this_seg%50];    /* sector */
  294.       n = 0;
  295.       do {
  296.          k = diskserv((wr?3:2), ndrive, 0, i, j, 1, buf);
  297.          if (k && ++n<3) redrive();
  298.       } while (k && n<3);
  299.  
  300.       if (cbreak) done(0); /* ??? */
  301.  
  302.       if (!k) { buf += BLKSIZE; --bl; } else skipsect();
  303.       ++this_seg;
  304.    }
  305. }
  306.  
  307. /* Interface routines */
  308. int dread(buf, n)
  309. char *buf; register n;
  310. {
  311.    register k = n / BLKSIZE;
  312.    if (n % BLKSIZE) return -1;
  313.    if (calibr == RAINBOW) rainbow(0, buf, k); else ibmdisk(0, buf, k);
  314.    return n;
  315. }
  316.  
  317. int dwrite(buf, n)
  318. char *buf; register n;
  319. {
  320.    n = (BLKSIZE-1 + n) / BLKSIZE;
  321.    if (calibr == RAINBOW) rainbow(1, buf, n); else ibmdisk(1, buf, n);
  322.    return BLKSIZE*n;
  323. }
  324.  
  325. int dback(n)
  326. register n;
  327. {
  328.    this_seg = this_seg > n ? this_seg-n : 0;
  329.    return n;
  330. }
  331. #endif
  332.